﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using COFE.Core.Filter;
using COFE.Core.Utils;
using COFE.Core.Profile;
using COFE.Core;
using System.Data.Common;
using System.Data.SqlClient;

namespace COFE.Data
{
    public static class COFEDB2Utils
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="customEntryList0"></param>
        /// <param name="skipPosition">Reserve this position.</param>
        private static void updatePosition(this COFE.Data.CustomEntryList customEntryList, COFEDB2 context, int skipPosition = -1, int skipCount = 0)
        {
            var contents = customEntryList.Contents.OrderBy(c => c.Position);
            var p = 0;
            foreach (var c in contents)
            {
                if (p == skipPosition)
                    p += skipCount;
                c.Position = p++;
            }
        }


        /// <summary>
        /// Insert an entry to DBEntryList
        /// </summary>
        /// <param name="customEntryList0"></param>
        /// <param name="dbEntry"></param>
        /// <param name="position">Insert to the specified position.</param>
        public static void InsertContent(this COFE.Data.CustomEntryList customEntryList, COFEDB2 context, int position, COFE.Data.Entry[] dbEntries)
        {
            customEntryList.RemoveContent(context, dbEntries);
            customEntryList.updatePosition(context, position, dbEntries.Count()); //update the current entries so it skip n items from the position.

            var startPos = position == -1 ? customEntryList.Contents.Count : Math.Min(position, customEntryList.Contents.Count);

            for (int i = 0; i < dbEntries.Length; i++)
            {
                var newContent = COFE.Data.CustomEntryList_Contents
                    .CreateCustomEntryList_Contents(customEntryList.EntryListId, dbEntries[i].EntryId);
                newContent.Position = startPos + i;

                customEntryList.Contents.Add(newContent);
            }
        }

        public static void InsertContent(this COFE.Data.CustomEntryList customEntryList, COFEDB2 context, int position, COFE.Data.Entry dbEntry)
        {
            customEntryList.InsertContent(context, position, new Entry[] { dbEntry });
        }

        public static void AddContent(this COFE.Data.CustomEntryList customEntryList, COFEDB2 context, COFE.Data.Entry dbEntry)
        {
            customEntryList.InsertContent(context, -1, dbEntry);
        }

        public static void RemoveContent(this COFE.Data.CustomEntryList customEntryList, COFEDB2 context, COFE.Data.Entry[] dbEntries)
        {
            foreach (var dbEntry in dbEntries)
            {
                var existingContent =
                            context.CustomEntryList_Contents
                                .FirstOrDefault((c) => c.EntryId == dbEntry.EntryId &&
                                    c.EntryListId == customEntryList.EntryListId);
                if (existingContent != null)
                    customEntryList.Contents.Remove(existingContent);             
            }
            customEntryList.updatePosition(context);
        }

        public static void RemoveContent(this COFE.Data.CustomEntryList customEntryList, COFEDB2 context, COFE.Data.Entry dbEntry)
        {
            customEntryList.RemoveContent(context, new Entry[] { dbEntry });
        }

        public static COFE.Data.Entry GetEntry(this COFE.Data.CustomEntryList_Contents content, COFEDB2 context)
        {
            return COFEDBShared.DBEntryManager.LookupEntry(context, content.EntryId);
        }

        public static bool UserExists(this COFEDB2 context, string userName)
        {
            return context.Users.Any(u => u.UserId == userName.ToLower());
        }

        public static User LookupUser(this COFEDB2 context, string userName)
        {
            return context.Users.FirstOrDefault(u => u.UserId == userName.ToLower());
        }

        public static User LookupUser(this COFEDB2 context, Guid authorizationKey)
        {
            return context.Users.FirstOrDefault(u => u.AuthorizeKey == authorizationKey);
        }

        public static User LookupUser(this COFEDB2 context, string userName, string password)
        {
            var encodedPassword = COFEDBShared.PasswordEncoder.Encode(password);
            return (from u in context.Users
                    where u.UserId == userName &&
                        u.UserSecret == encodedPassword
                    select u).FirstOrDefault();
        }

        public static User CreateUser(this COFEDB2 context, string userName, string password)
        {
            var encodedPassword = COFEDBShared.PasswordEncoder.Encode(password);
            User newUser = User.CreateUser(userName, encodedPassword, DateTime.UtcNow, DateTime.UtcNow, Guid.NewGuid());
            context.Users.AddObject(newUser);
            context.SaveChanges();
            return newUser;
        }

        /// <summary>
        /// Update login time, any new authorize primVolId if expired.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="currentUser"></param>
        public static void RefreshUser(this COFEDB2 context, User user, bool updateAuthorizeKey)
        {
            user.LoginTime = DateTime.UtcNow;
            if (updateAuthorizeKey && user.LoginTime.Subtract(DateTime.UtcNow) > COFEDBShared.TTLUserExpire)
                user.AuthorizeKey = Guid.NewGuid();            
        }


    }
}
